package org.skydiveapplibrary.repository;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import org.skydiveapplibrary.data.Aircraft;
import org.skydiveapplibrary.data.Database;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class AircraftRepository
{
	// jump count query format
	private static final String JUMP_COUNT_QUERY_FORMAT =
		"select count(*) " +
		"from log_entry " +
		"where aircraft = {0}";
	
	private Database database;
	
	public AircraftRepository(Context context)
	{
		database = new Database(context);
	}
	
	public List<Aircraft> getAllAircrafts()
	{
		return getAircrafts(null);
	}
	
	public List<Aircraft> getAircrafts()
	{
		return getAircrafts(Database.AIRCRAFT_ACTIVE + " = " + 1);
	}
	
	private List<Aircraft> getAircrafts(String where)
	{
		List<Aircraft> aircrafts = new ArrayList<Aircraft>();
		
		SQLiteDatabase db = database.getReadableDatabase();
		Cursor cursor = null;
		try
		{
			// perform query
			cursor = db.query(
					Database.AIRCRAFT_TABLE,
					Database.AIRCRAFT_ALL_COLUMNS,
					where,
					null, null, null,
					Database.AIRCRAFT_NAME);
			
			// iterate over results
			while (cursor.moveToNext())
			{
				// create aircrafts
				Aircraft aircraft = createAircraft(cursor);
				aircrafts.add(aircraft);
			}
		}
		finally
		{
			// close cursor
			if (cursor != null)
			{
				cursor.close();
			}
			// close database
			db.close();
		}
		
		return aircrafts;
	}
	
	public Aircraft findAircraft(String name)
	{
		return getAircraft(Database.AIRCRAFT_NAME + " = ?", name);
	}
	
	public Aircraft getAircraft(int id)
	{
		return getAircraft(Database.AIRCRAFT_ID + " = ?", String.valueOf(id));
	}
	
	public Aircraft getDefaultAircraft()
	{
		Aircraft aircraft = null;
		
		SQLiteDatabase db = database.getReadableDatabase();
		Cursor cursor = null;
		try
		{
			// perform query
			cursor = db.query(
					Database.AIRCRAFT_TABLE,
					Database.AIRCRAFT_ALL_COLUMNS,
					Database.AIRCRAFT_DEFAULT + " = " + 1,
					null, null, null, null);
			
			if (cursor.moveToFirst())
			{
				aircraft = createAircraft(cursor);
			}
		}
		finally
		{
			// close cursor
			if (cursor != null)
			{
				cursor.close();
			}
			// close db
			db.close();
		}
		
		return aircraft;
	}
	
	public Aircraft getFromUniqueId(String uniqueId)
	{
		return getAircraft(Database.AIRCRAFT_UNIQUE_ID + " = ?", uniqueId);
	}
	
	private Aircraft getAircraft(String where, String... whereParams)
	{
		Aircraft aircraft = null;
		
		SQLiteDatabase db = database.getReadableDatabase();
		Cursor cursor = null;
		try
		{
			// perform query
			cursor = db.query(
					Database.AIRCRAFT_TABLE,
					Database.AIRCRAFT_ALL_COLUMNS,
					where,
					whereParams,
					null,
					null,
					null);
			
			if (cursor.moveToFirst())
			{
				aircraft = createAircraft(cursor);
			}
		}
		finally
		{
			// close cursor
			if (cursor != null)
			{
				cursor.close();
			}
			// close database
			db.close();
		}
		
		return aircraft;
	}
	
	public void addAircraft(Aircraft aircraft)
	{
		// set modified
		if (aircraft.getLastModifiedUtc() == null)
		{
			aircraft.setLastModifiedUtc(new Date(System.currentTimeMillis()));
		}
		
		// set uniqueId
		if (aircraft.getUniqueId() == null || aircraft.getUniqueId() == "")
		{
			aircraft.setUniqueId(UUID.randomUUID().toString());
		}
		
		// get insert values
		ContentValues values = createContentValues(aircraft);
		
		// do insert
		SQLiteDatabase db = database.getWritableDatabase();
		try
		{
			if (aircraft.isDefault())
			{
				// clear other default aircraft
				clearDefaultAircraft(db);
			}
			
			// do insert
			long id = db.insert(Database.AIRCRAFT_TABLE, null, values);
			aircraft.setId((int)id);
		}
		finally
		{
			// close db
			db.close();
		}
	}
	
	public void updateAircraft(Aircraft aircraft)
	{
		updateAircraft(aircraft, true);
	}
	
	public void updateAircraft(Aircraft aircraft, boolean updateLastModified)
	{
		// set modified
		if (updateLastModified)
		{
			aircraft.setLastModifiedUtc(new Date(System.currentTimeMillis()));
		}
		
		// get update values
		ContentValues values = createContentValues(aircraft);
		
		SQLiteDatabase db = database.getWritableDatabase();
		try
		{
			if (aircraft.isDefault())
			{
				// clear other default aircraft
				clearDefaultAircraft(db);
			}
			
			// do update
			db.update(Database.AIRCRAFT_TABLE,
					values,
					Database.AIRCRAFT_ID + " = " + aircraft.getId(),
					null);
		}
		finally
		{
			// close db
			db.close();
		}
	}
	
	public void deleteAircraft(Aircraft aircraft)
	{
		SQLiteDatabase db = database.getWritableDatabase();
		try
		{
			// create update values
			ContentValues values = new ContentValues();
			values.put(Database.AIRCRAFT_ACTIVE, false);
					
			// deactivate
			db.update(
					Database.AIRCRAFT_TABLE,
					values,
					Database.AIRCRAFT_ID + " = " + aircraft.getId(),
					null);					
		}
		finally
		{
			// close db
			db.close();
		}
	}
	
	private void clearDefaultAircraft(SQLiteDatabase db)
	{
		ContentValues values = new ContentValues();
		values.put(Database.AIRCRAFT_DEFAULT, 0);
		
		db.update(
				Database.AIRCRAFT_TABLE,
				values,
				null, null);
	}
	
	private Aircraft createAircraft(Cursor cursor)
	{
		Aircraft aircraft = new Aircraft();
		
		aircraft.setId(Database.getInteger(cursor, Database.AIRCRAFT_ID));
		aircraft.setActive(Database.getBoolean(cursor, Database.AIRCRAFT_ACTIVE));
		aircraft.setName(Database.getString(cursor, Database.AIRCRAFT_NAME));
		aircraft.setDefault(Database.getBoolean(cursor, Database.AIRCRAFT_DEFAULT));
		aircraft.setNotes(Database.getString(cursor, Database.AIRCRAFT_NOTES));
		aircraft.setJumpCount(getJumpCount(aircraft.getId(), database.getReadableDatabase()));
		aircraft.setLastModifiedUtc(Database.getDateTime(cursor, Database.AIRCRAFT_LAST_MODIFIED_UTC));
		aircraft.setUniqueId(Database.getString(cursor, Database.AIRCRAFT_UNIQUE_ID));
		return aircraft;
	}
	
	private ContentValues createContentValues(Aircraft aircraft)
	{
		ContentValues values = new ContentValues();
		
		values.put(Database.AIRCRAFT_ACTIVE, aircraft.isActive());
		values.put(Database.AIRCRAFT_NAME, aircraft.getName());
		values.put(Database.AIRCRAFT_DEFAULT, aircraft.isDefault());
		values.put(Database.AIRCRAFT_NOTES, aircraft.getNotes());
		values.put(Database.AIRCRAFT_LAST_MODIFIED_UTC, Database.dateTimeToString(aircraft.getLastModifiedUtc()));
		values.put(Database.AIRCRAFT_UNIQUE_ID, aircraft.getUniqueId());
		
		return values;
	}
	
	private int getJumpCount(int aircraftId, SQLiteDatabase db)
	{
		// construct query
		String query = MessageFormat.format(JUMP_COUNT_QUERY_FORMAT, aircraftId);
		// result
		int result = 0;
		
		// execute query
		Cursor cursor = null;
		try
		{
			cursor = db.rawQuery(query, null);
			
			// get results
			if (cursor.moveToFirst())
			{
				result = cursor.getInt(0);
			}
		}
		finally
		{
			// close cursor
			if (cursor != null)
			{
				cursor.close();
			}
		}
		
		return result;
	}
	
	public boolean exists(String where, String... whereParams)
	{
		SQLiteDatabase db = database.getReadableDatabase();
		Cursor cursor = null;
		try
		{
			// perform query
			cursor = db.query(
					Database.AIRCRAFT_TABLE,
					Database.AIRCRAFT_ALL_COLUMNS,
					where + " = ?",
					whereParams,
					null,
					null,
					null);
			
			return cursor.getCount() > 0;
		}
		finally
		{
			// close cursor
			if (cursor != null)
			{
				cursor.close();
			}
			// close db
			db.close();
		}
	}
}